---
title: "Apache on Ubuntu 18.04 on SSL: HTTPS Tutorial with Namecheap and OpenSSL"
date:  2020-04-24
category:  TechTips
---

<a id="return_footnote_1"></a> This is a tutorial on configuring an [Apache web
server](https://httpd.apache.org/), running on Ubuntu 18.04 server, to use
HTTPS, or HTTP over SSL/TLS<sup>[1](#footnote_1)</sup> to encrypt and secure
users' communication with your website or web app.  This leads to more secure
use of your website, particularly if your users are inputting passwords or
sensitive information.

A quick search in your [favourite search engine](https://duckduckgo.com) will reveal
that the web is moving toward https everywhere, and you should too.  It's safer.
It's better.  But it's a bit confusing if you've never done it before.

This is a guide for someone managing an Apache web server of some sort (probably
a VPS in the cloud, but could be a virtual machine, a computer in your home [be
careful if you're doing that, and definitely use HTTPS] or workplace, or
something else), who has http configured, has their website or web app running
pretty well, and now wishes to add HTTPS support.  You will need shell access to
the server you will be adding the certificate to.

The process can easily take several hours if you're not sure where to start,
where to look for help, what the various terms mean and what you need, let alone
what is modern or deprecated, what is performant, or what is vulernable.  My
hope is that if the scenario in this walkthrough maps closely to your use case,
you will be able to complete the process very quickly (under an hour),
understand what you're doing at each step and why, and finish the process with
more knowledge than you started, in addition to having a site now working over
HTTPS.  A picture of the green padlock on the address bar (which is what Firefox
uses to indicate the site is using HTTPS) will be our victory flag.

<img src="assets/ssl.jpg" alt="ssl icon" width="60%"/>

Here is our programme for this evening:

1. [TLS/SSL certificate creation or purchase](#section_1)
2. [Generate Certificate Signing Request (CSR)](#section_2)
3. [Domain-control Validation (DCV)](#section_3)
4. [Install .crt an .bundle files on server](#section_4)
5. [Cross Fingers](#section_5)
6. [Setup Redirect from HTTP to HTTPS](#section_6)
7. [Conclusion](#section_7)

## <a id="section_1"></a> 1. TLS/SSL certificate creation or purchase

The first step of the process is to request a certificate.  I am aware of 
3 ways to do this:

1. Purchase one from a certificate authority like Comodo, GeoTrust, or Symantec.
2. Request one using [Let's Encrypt](https://letsencrypt.org/)
3. Generate your own, self-signed certificate.

I won't be covering option 3 here, as these are not as secure as one validated
by a certificate authority (CA).  These are fine for internal networks or
testing purposes, but should probably be avoided for most productino
enviroments.  For a bit more on this option, see [Wikipedia's entry](https://en.wikipedia.org/wiki/Self-signed_certificate).

Options 1 and 2 are quite similar, under the hood, though option 2, using Let's
Encrypt, may require marginally more [technical
sophistication](https://www.securemac.com/news/the-securemac-interview-michael-hartl-on-technical-sophistication)
than option 1.  Maybe not though.  In a vacuum, I'd recommend using Let's
Encrypt, as they are a great organization worth supporting, they have excellent
documentation, and you get, for free, the same level of protection offered by
most low-cost certificate authorities.

For the purposes of this article, however, we're going to cover option 1: buying
a certificate from a CA.  Most hosting providers, like Namecheap and GoDaddy,
offer integrations with CA's, to allow you purchase and install certificates, so
the friction is pretty minimal.  As an example of cost, at the time of this
writing [Namecheap offers basic
certificates](https://www.namecheap.com/security/ssl-certificates/) for as low
as $5.88/yr (higher-tier offerings can be significantly more, $100 and up).

### 1.1 Buying a Certificate through Namecheap

Here are the steps for purchasing a certificate through Namecheap.  These steps
will, of course, vary according to which provider you use, but I include them
here as an example of the process.  It is simple enough.

1. Log in to Namecheap hosting account
2. Navigate to their [ssl-certificates
   page](https://www.namecheap.com/security/ssl-certificates/).
3. Choose a CA offering, and click "Buy Now"
4. Confirm order / pay
5. From Namecheap dashboard, navigate to Product List -> SSL Certificates.
6. Click "Activate" for your newly purchased cert

After clicking Activate, you should be brought to a screen that looks like this:

<img src="assets/nc_csr.png" alt="Namecheap CSR screen" width="60%"/>

We will come back to this screen after we generate a CSR.

Once you've purchased the certificate, it's time to begin the Certificate
Signing Request process.

## <a id="section_2"></a> 2. Generate certificate Signing Request (CSR)

A certificate signing request (CSR) is a block of text that you submit to
a certificate authortity in the certificate activation process.  The CSR is
a combination of a [public key](https://en.wikipedia.org/wiki/Public_key) and
some information about you (i.e., the the applicant or applicant organization).
You can read more about CSRs on
[Wikipedia](https://en.wikipedia.org/wiki/Certificate_signing_request):

To generate our CSR, we are going to use a package called
[OpenSSL](https://www.openssl.org/).  It describes itself this way: "OpenSSL is
a robust, commercial-grade, and full-featured toolkit for the Transport Layer
Security (TLS) and Secure Sockets Layer (SSL) protocols. It is also
a general-purpose cryptography library."  We will be using it to generate our
CSR.

In Linux land, many distros either ship with, or include in their package
repositories, the [OpenSSL package].  Typing `$ which openssl` on GNU/Linux should
indicate whether you have it installed on your server (no output means no
installation).  If it's not installed, you should be able to find it in your
pakckage manager easily enough, e.g., in Ubuntu, it is simply `$ sudo apt install
openssl`.  Installing on BSD, OSX, or Windows I leave as an exercise to the
reader.  As a last resort, the source code, Apache-licensed, is available on
[openssl.org](https://www.openssl.org).

To generate the CSR, first log in to your server, and remove a deprecated config
line from the openssl configuration file (found at /etc/ssl/openssl.cnf):

\#RANDFILE  = $ENV::HOME/.rnd

Then server and run this command to generate your private key and CSR:

`$ openssl req -new -newkey rsa:2048 -nodes -keyout {yourdomain.com}.key -out {yourdomain.com}.csr`

The program will then prompt you for several pieces of information, about your
organizational name, location, etc.  

Here are the fields you will be prompted to fill in:

- Country Name (2 letter code) [AU]:
- State or Province Name (full name) [Some-State]:
- Locality Name (eg, city) []:
- Organization Name (eg, company) [Internet Widgits Pty
  Ltd]:
- Organizational Unit Name (eg, section) []:
- Common Name (e.g. server FQDN or YOUR name) []:
- Email Address []:

- Please enter the following 'extra' attributes
to be sent with your certificate request
- A challenge password []:
- An optional company Name:

The one that may be confusing here is the "Common Name".  This is where you want
to put your website address, e.g., yoursite.com.

For basic certificates (known as 'domain validation' certs), like the
PositiveSSL one mentioned above, this additional information will not show up to
visitors to your site.  If you purchase fancier certs with organization
validation or extended validation, this information will be publicly visible.
See
[here](https://en.wikipedia.org/wiki/Organization_Validation_Certificate#Validation_levels)
for more about validation levels of certificates.

This will generate {yourdomain.com}.csr and {yourdomain.com}.key in the
directory where you ran the command.

After generating the CSR, you will need to submit it to the certificate
authority.  Returning to the CSR screen from Step 1, above, paste the contents
of the {yourdomain.com}.csr into the text box.  These steps will again differ
according to the platform you are using, but they should be roughly this (maybe
it's a paste, maybe it's an upload).

From here you may be asked to confirm a few details from the certificate.

Next up is Domain Control Validation, a process of demonstrating to the CA that
you control the domain for which the certificate is being requested / issued.

## <a id="section_3"></a> 3. Domain-control Validation

After pasting the contents of your CSR, you will be asked to demonstrate Domain
Control Validation (DCV).  There are 3 ways to do this:

1. Email Validation - Receive an email to an address associated with the domain (e.g., admin
   @yoursite.com)
2. HTTP Validation -upload a particular file to a particular location on your
   server 
3. DNS-based validation - create a CNAME record at your domain

Options 2 and 3 are slightly more involved than option 1, so if possible, I'd
recommend the first option.  If you are using option 2 or 3, the issuer should
provide you with instructions on what file to download or what content the DNS
record must have.

If you choose option 1, you should simply receive an email with the files you
need to upload to your server: a .crt file, a .bundle file, or maybe both

The next step will be to copy this certicate to your server (see step 4, below).

## <a id="section_4"></a> 4. Install .crt / .bundle file on server

Assuming everything is in order, the CA will then cryptographically sign
a certificate using it's private key, and then send you that certificate.

A certificate file has contents that look like this:

<img src="assets/certificate.png" alt="ssl certificate" width="60%"/>

This part might be tricky.  You may receive just a .crt file, or you may receive
both a .ca-bundle and a .crt file, or maybe just a .ca-bundle file.  Some
providers may offer different files again. When ordering from PositiveSSL
through Namecheap, I receive both both a .crt file and a .ca-bundle file.  The
.crt file is the certificate file itself, and here is Namecheap's description of
the .ca-bundle file: "CA bundle is a file that contains root and intermediate
certificates. The end-entity certificate along with a CA bundle constitutes the
certificate chain"
[source](https://www.namecheap.com/support/knowledgebase/article.aspx/986/69/what-is-ca-bundle).
See the linked article for more information.

### 4.1 Optional - Concatenate .crt and .ca-bundle

The first sub-step, which I believe is not strictly necessary, but probably
helps (I need to do a bit more digging on this), is to concatenate the ca-bundle
file onto the end of the crt file (in Linux, make a backup of your files
(probably a .zip with the files), then run cat your-domain.ca-bundle >>
your-domain.crt.

### 4.2 Move files into place
sudo/
Now we get into the server-side work.  First, you'll need to copy your .crt file
(concatenated or not) and your .key (your private key file) to 2 specific
directories on the server.  On Ubuntu 18.04, you'll want to do this:
- .crt file ->  /etc/ssl/certs
- .key file -> /etc/ssl/private
These could probably safely live in other locations, but best to stick with
convention, here.

These 2 files will be referenced in your Apache config, momentarily.

### 4.3 Create an SSL-version of your site config for Apache

The next step is to create a site configuration file for Apache to read, that
references the .crt and .key files.  In Ubuntu 18.04, you'll want to create this
in /etc/apache2/sites-available.  The simplest way to do it is simply copy the
existing HTTP config, then modify a few things:

- Change <VirtualHost *:80> to <VirtualHost *:443>

In case this is unfamiliar - port 80 is reserved for HTTP traffic, while port
443 is reserved for HTTPS traffic.

Then add these lines:  
- SSLEngine on  
- SSLCertificateFile /etc/ssl/certs/yoursite.crt  
- SSLCertificateKeyFile /etc/ssl/private/yoursite.key  

Note: you may have seen a "Listen 443" directive in Apache config files before.
You probably don't need to manually add this anywhere with Ubuntu 18.04 and
recent versions of apache2. If you look at /etc/apache2/ports.conf, you should
see the following block:

\<IfModule ssl_module\>
    Listen 443
\</IfModule\>

So if the ssl module is enabled, the server will listen on port 443, and the
VirtualHost entry you made above will catch the traffic.

### Enable SSL and the ssl-site-config

Next we'll use the apache command line interface to enable SSL and enable the
new site config (run these as sudo/root):

    $ sudo a2enmod ssl
    $ sudo a2ensite yoursite-ssl
    $ sudo apachectl -t
    $ sudo service apache2 reload

Note - `sudo apachectl -t` checks your config files, and throws an error if there are
syntax problems.  Good sanity check before rebooting into a broken server
config.

## <a id="section_5"></a> 5. Cross Fingers

Pretty self-explanatory.

Navigate to https://yoursite.com and hope that you see the little green padlock
(or whatever symbol your browser uses to indicate that the site is using HTTPS).

## <a id="section_6"></a> 6. Setup Redirect from HTTP to HTTPS

Now that you have SSL working (hopefully), you will probably want to point all
traffic to port 443.  There are two basic steps to this - enable the Apache
rewrite module, and change your original HTTP Apache config to redirect to your
HTTPS one.

`sudo a2enmod rewrite`

This will enable the rewrite module.

Then, if you want to redirect all traffic to HTTPS, gut your HTTP config.  Just
keep the following:
<VirtualHost *:80>
    ServerName yoursite.com
    Redirect permanent / https://yoursite.com
</VirtualHost>

Simple.  If you need more complex redirects, for example only using HTTPS with
sub-domains or only certain pages, you'll need to do some searching on the web.

## <a id="section_7"></a> 7. Conclusion

If all went according to plan, you will now have a TLS/SSL protected website.
Your users can feel safe in the warm glow of encryption, and you can feel good
about the bits you're flinging through the aether.  If it didn't feel free to
email me.  Happy serving!

##### Footnote:

<a id="footnote_1"></a>1.  HTTPS means both *HTTP over SSL* and *HTTP over TLS*.
See [here](https://www.globalsign.com/en/blog/ssl-vs-tls-difference) for a great
article on the difference between SSL and TLSl and
[here](https://www.leaderssl.com/news/471-how-to-disable-outdated-versions-of-ssl-tls-in-apache)
for a tutorial on disabling deprecated SSL and TLS versions, if you so desire,
after configuring the HTTPS defaults. To whit: back the tutorial.
<sub>[return](#return_footnote_1)</sub>
